<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="824.48">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Helvetica}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica; min-height: 14.0px}
p.p3 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica}
p.p4 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco}
p.p5 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #9d1c12}
p.p6 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; min-height: 12.0px}
p.p7 {margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco; color: #606060}
span.s1 {font: 18.0px Helvetica}
span.s2 {color: #0026b4}
span.s3 {color: #000000}
span.s4 {color: #9d1c12}
span.Apple-tab-span {white-space:pre}
</style>
</head>
<body>
<p class="p1"><span class="s1"><b>Squiz<span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span></b></span><b>Wave squeezer. Maybe a kind of pitch shifter.</b></p>
<p class="p2"><br></p>
<p class="p3"><b>Squiz.ar(in, pitchratio, zcperchunk, memlen)</b></p>
<p class="p2"><br></p>
<p class="p3">A simplistic pitch-raising algorithm. It's not meant to sound natural; its sound is reminiscent of some weird mixture of filter, ring-modulator and pitch-shifter, depending on the input.</p>
<p class="p2"><br></p>
<p class="p3"><b>pitchratio</b> is the ratio by which pitch will be raised (e.g. pitchratio of 2 will raise by one octave). Only upwards pitch-shifts are possible so a value <i>below</i> 1 will have no effect.</p>
<p class="p2"><br></p>
<p class="p3">The algorithm works by cutting the signal into fragments (delimited by upwards-going zero-crossings) and squeezing those fragments in the time domain (i.e. simply playing them back faster than they came in), leaving silences imbetween.<span class="Apple-converted-space"> </span></p>
<p class="p2"><br></p>
<p class="p3"><b>zcperchunk</b> indicates how many positive-going zero-crossings are used to delimit a chunk. (Only positive integer values make sense.)</p>
<p class="p2"><br></p>
<p class="p3"><b>memlen</b> is the amount (in seconds) of memory the unit allocates internally to remember each fragment, i.e. the longest a given fragment can become. The default should be fine for most signals. Raising it higher will use more real-time memory and probably won't sound very different (especially if zcperchunk is low).</p>
<p class="p2"><br></p>
<p class="p3">All the parameters apart from memlen can be modulated.</p>
<p class="p2"><br></p>
<p class="p3">This UGen is dedicated to Suburban Base Records. (It doesn't sound like them, but was half-inspired by them.)</p>
<p class="p2"><br></p>
<p class="p2"><br></p>
<p class="p3"><b>Examples</b></p>
<p class="p2"><br></p>
<p class="p3">In both these examples, moving the mouse left/right varies <i>pitchratio</i>, while moving it up/down varies<span class="Apple-converted-space">  </span><i>zcperchunk</i>. If you watch the scope it illustrates fairly well what's happening.</p>
<p class="p2"><br></p>
<p class="p4">s = <span class="s2">Server</span>.internal;</p>
<p class="p4">s.boot;</p>
<p class="p5">// On a simple sine wave</p>
<p class="p4">x = {<span class="s2">Squiz</span>.ar(<span class="s2">SinOsc</span>.ar, <span class="s2">MouseX</span>.kr(1, 10, 1), zcperchunk: <span class="s2">MouseY</span>.kr(1, 10), mul:0.1).dup}.play(s);</p>
<p class="p4">x.free;</p>
<p class="p5">// Scope is helpful for visualising what's going on</p>
<p class="p4">x = {<span class="s2">Squiz</span>.ar(<span class="s2">SinOsc</span>.ar, <span class="s2">MouseX</span>.kr(1, 10, 1), zcperchunk: <span class="s2">MouseY</span>.kr(1, 10), mul:0.1).dup}.scope;</p>
<p class="p4">x.free;</p>
<p class="p6"><br></p>
<p class="p6"><br></p>
<p class="p5">// On a sample of some sort - choose one...</p>
<p class="p7"><span class="s3">b = </span><span class="s2">Buffer</span><span class="s3">.read(s,</span>"sounds/a11wlk01.wav"<span class="s3">);</span></p>
<p class="p7"><span class="s3">b = </span><span class="s2">Buffer</span><span class="s3">.read(s,</span>"sounds/amenfast.wav"<span class="s3">);</span></p>
<p class="p4">(</p>
<p class="p4">x = {</p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="s2">var</span> sig;</p>
<p class="p4"><span class="Apple-tab-span">	</span>sig = <span class="s2">PlayBuf</span>.ar(1, b.bufnum, <span class="s2">BufRateScale</span>.kr(b.bufnum) * 0.5, startPos: 92898, loop: 1);</p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="s2">Squiz</span>.ar(sig, <span class="s2">MouseX</span>.kr(1, 100, 1), zcperchunk: <span class="s2">MouseY</span>.kr(1, 10), mul:0.5).dup</p>
<p class="p4">}.play(s);</p>
<p class="p4">)</p>
<p class="p4">x.free;</p>
<p class="p4">b.free;</p>
<p class="p6"><br></p>
<p class="p6"><br></p>
<p class="p5">// Let's make it a bit more complicated. By analysing the signal we can change the Squiz sound algorithmically.</p>
<p class="p4">s.boot;</p>
<p class="p7"><span class="s3">b = </span><span class="s2">Buffer</span><span class="s3">.read(s,</span>"sounds/amenfast.wav"<span class="s3">);</span></p>
<p class="p4">c = <span class="s2">Buffer</span>.alloc(s, 512);</p>
<p class="p4">(</p>
<p class="p4">x = {</p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="s2">var</span> sig, chain, centroid, hicent, locent, fraccent, fraccentl, heaviness, heaviness2, kick2trig, kick2;</p>
<p class="p4"><span class="Apple-tab-span">	</span>sig = <span class="s2">PlayBuf</span>.ar(1, b.bufnum, <span class="s2">BufRateScale</span>.kr(b.bufnum) * 0.5, <span class="s4">/*startPos: 92898, */</span>loop: 1);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p5"><span class="s3"><span class="Apple-tab-span">	</span></span>// kick2 to emphasise the main downbeats</p>
<p class="p4"><span class="Apple-tab-span">	</span>kick2trig = <span class="s2">Impulse</span>.kr(<span class="s2">BufDur</span>.kr(b.bufnum).reciprocal * 4);</p>
<p class="p4"><span class="Apple-tab-span">	</span>kick2 = SinOsc.ar(50 + EnvGen.ar(Env.perc(0.001, 0.01, 1000, -10), kick2trig));</p>
<p class="p4"><span class="Apple-tab-span">	</span>kick2 = <span class="s2">EnvGen</span>.ar(<span class="s2">Env</span>.perc, kick2trig) * kick2 * 0.3;</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p4"><span class="Apple-tab-span">	</span>chain = <span class="s2">FFT</span>(c.bufnum, sig);</p>
<p class="p5"><span class="s3"><span class="Apple-tab-span">	</span></span>//centroid = FFTCentroid.kr(chain).log.max(0.000001);</p>
<p class="p4"><span class="Apple-tab-span">	</span>centroid = <span class="s2">FFTPercentile</span>.kr(chain, 0.9);<span class="s4">//.log.max(0.000001);</span></p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p4"><span class="Apple-tab-span">	</span>hicent = <span class="Apple-converted-space">    </span><span class="s2">Amplitude</span>.kr(centroid, 0, 10);</p>
<p class="p4"><span class="Apple-tab-span">	</span>locent = 10000 - <span class="s2">Amplitude</span>.kr(10000 - centroid, 0, 10);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p4"><span class="Apple-tab-span">	</span>fraccent = ((centroid - locent) / (hicent - locent)).min(1).max(0);</p>
<p class="p4"><span class="Apple-tab-span">	</span>fraccentl = <span class="s2">Latch</span>.kr(fraccent, <span class="s2">Onsets</span>.kr(chain));</p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="s2">Out</span>.kr(0, fraccentl);</p>
<p class="p5">//<span class="Apple-tab-span">	</span>fraccent.poll;</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p5"><span class="s3"><span class="Apple-tab-span">	</span></span>//heaviness = MouseX.kr(0,1);</p>
<p class="p5"><span class="s3"><span class="Apple-tab-span">	</span></span>//heaviness2 = MouseY.kr(0,1);</p>
<p class="p4"><span class="Apple-tab-span">	</span>heaviness<span class="Apple-converted-space">  </span>= <span class="s2">LFPar</span>.kr(0.016, 0, 0.5, 0.5);</p>
<p class="p4"><span class="Apple-tab-span">	</span>heaviness2 = <span class="s2">LFPar</span>.kr(0.016, 1, 0.5, 0.5);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p5"><span class="s3"><span class="Apple-tab-span">	</span></span>// we don't go really mental until we've got going</p>
<p class="p4"><span class="Apple-tab-span">	</span># heaviness, heaviness2 = [heaviness, heaviness2] * <span class="s2">Line</span>.kr(0.1, 1, 100);</p>
<p class="p6"><span class="Apple-tab-span">	</span></p>
<p class="p4"><span class="Apple-tab-span">	</span>kick2 + <span class="s2">Squiz</span>.ar(sig,<span class="Apple-converted-space"> </span></p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>( <span class="Apple-converted-space">  </span>fraccentl<span class="Apple-converted-space">  </span>* <span class="s2">LFNoise2</span>.kr(0.1).exprange(1, 100) * heaviness) +<span class="Apple-converted-space"> </span></p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>((1-fraccentl) * <span class="s2">LFNoise2</span>.kr(0.1).exprange(1, 100) * heaviness2) +</p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>0.8,<span class="Apple-converted-space"> </span></p>
<p class="p4"><span class="Apple-tab-span">	</span><span class="Apple-tab-span">	</span>zcperchunk: <span class="s2">LFNoise2</span>.kr(0.1).range(1, 10), mul:0.5).dup</p>
<p class="p5"><span class="s3"><span class="Apple-tab-span">	</span></span>//sig</p>
<p class="p4">}.play(s);</p>
<p class="p4">)</p>
<p class="p5">//s.scope5</p>
<p class="p4">x.free;</p>
<p class="p4">b.free;</p>
</body>
</html>
